﻿namespace NKernel.Core.Impl
{
    using System.Reflection;

    /// <summary>
    /// Instance of the ComponentObject
    /// </summary>
    internal sealed class ComponentObject : IComponentObject
    {
        #region Fields

        private readonly string assemblyName;
        private readonly string componentImplementation;
        private readonly string componentInterface;
        private readonly string componentName;
        private readonly string componentVersion;

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="ComponentObject"/> class.
        /// </summary>
        /// <param name="componentDescriptor">The component descriptor.</param>
        public ComponentObject(ComponentDescriptor componentDescriptor)
        {
            State = ComponentStateType.Uninitialised;
            assemblyName = componentDescriptor.AssemblyName;
            componentName = componentDescriptor.ComponentName;
            componentInterface = componentDescriptor.ComponentInterface;
            componentImplementation = componentDescriptor.ComponentImplementation;
            componentVersion = componentDescriptor.Assembly.GetName().Version.ToString();
        }

        #endregion Constructors

        #region Properties

        public string AssemblyName
        {
            get
            {
                return assemblyName;
            }
        }

        public string ComponentImplementation
        {
            get
            {
                return componentImplementation;
            }
        }

        public string ComponentInterface
        {
            get
            {
                return componentInterface;
            }
        }

        public object ComponentInterfaceInstance
        {
            set; get;
        }

        public string ComponentName
        {
            get
            {
                return componentName;
            }
        }

        public string ComponentVersion
        {
            get
            {
                return componentVersion;
            }
        }

        public ComponentStateType State
        {
            get; set;
        }

        #endregion Properties

        #region Methods

        public void Cleanup()
        {
            if (ComponentInterfaceInstance == null)
            {
                return;
            }

            foreach (string cleanupMethod in KernelProperties.CleanupMethods)
            {
                MethodInfo methodInfo = ComponentInterfaceInstance.GetType().GetMethod(cleanupMethod);
                if (methodInfo == null)
                {
                    continue;
                }

                methodInfo.Invoke(ComponentInterfaceInstance, new object[] { });
                break;
            }
        }

        public void Init()
        {
            if (ComponentInterfaceInstance == null)
            {
                return;
            }

            foreach (string initMethod in KernelProperties.InitMethods)
            {
                MethodInfo methodInfo = ComponentInterfaceInstance.GetType().GetMethod(initMethod);
                if (methodInfo == null)
                {
                    continue;
                }

                methodInfo.Invoke(ComponentInterfaceInstance, new object[] { });
                break;
            }
        }

        public void Start()
        {
            if (ComponentInterfaceInstance == null)
            {
                return;
            }

            foreach (string startMethod in KernelProperties.StartMethods)
            {
                MethodInfo methodInfo = ComponentInterfaceInstance.GetType().GetMethod(startMethod);
                if (methodInfo == null)
                {
                    continue;
                }

                methodInfo.Invoke(ComponentInterfaceInstance, new object[] { });
                break;
            }
        }

        public void Stop()
        {
            if (ComponentInterfaceInstance == null)
            {
                return;
            }

            foreach (string stopMethod in KernelProperties.StopMethods)
            {
                MethodInfo methodInfo = ComponentInterfaceInstance.GetType().GetMethod(stopMethod);
                if (methodInfo == null)
                {
                    continue;
                }

                methodInfo.Invoke(ComponentInterfaceInstance, new object[] { });
                break;
            }
        }

        #endregion Methods
    }
}